package collecting

import (
	"context"
	"sync"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/columnd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/common"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/groupd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/infod"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd/repo/mgorepo"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/log"
)

// Collecting 信息收集器
// 发布的信息添加到信息收集器后
type Collecting interface {
	Append(i *infod.InfoAggregate)
	Del(infoid string)
	AddGroup(g *groupd.GroupAggregate)
	DelGroup(g *groupd.GroupAggregate)
	Start()
}

// NewCollecting 信息收集器
func NewCollecting(d ddd.Domain) Collecting {
	c := &collecting{
		d:      d,
		gas:    make([]*groupd.GroupAggregate, 0),
		gasmap: make(map[string]*groupd.GroupAggregate),
		gs:     d.SubDomain(groupd.DomainID).(groupd.GroupDomain).GroupService(),
		gar:    d.SubDomain(groupd.DomainID).(groupd.GroupDomain).GroupAggregateRoot(),
		m:      make(chan *mcoll, 1024),
		car:    d.SubDomain(columnd.DomainID).(columnd.ColumnDomain).ColumnAggregateRoot(),
	}

	return c
}

type collecting struct {
	d      ddd.Domain
	gas    []*groupd.GroupAggregate
	gasmap map[string]*groupd.GroupAggregate
	lock   sync.RWMutex
	m      chan *mcoll
	gs     groupd.GroupService
	gar    groupd.GroupAggregateRoot
	car    columnd.ColumnAggregateRoot
}

func (c *collecting) Start() {
	ctx := ddd.NewContext(context.Background(), "", log.Logger())
	mgorepo.SetContextDB(ctx, c.d)
	defer mgorepo.ReleaseDB(ctx)
	pi := common.PageInfo{
		PageID:   "",
		Mode:     1,
		PageSize: 100,
	}
	for {
		pr, gs, err := c.gar.QueryPage(ctx, groupd.GroupSearch{
			Range:  0,
			Kind:   groupd.GroupKindAuto,
			Status: []groupd.GStatus{groupd.GSNormal},
		}, pi)

		if err != nil {
			panic("初始化加载信息组失败")
		}
		log.Infof("读取%d个信息组:", len(gs))
		for _, g := range gs {
			c.AddGroup(&g)
		}
		log.Infof("加载了%d个信息组:", len(c.gas))
		if pr.End == 1 || len(gs) == 0 {
			break
		}
	}
	go c.runAppInfo()
}
func (c *collecting) runAppInfo() {
	defer func() {
		log.Warn("信息组信息收集goroute 停止运行！")
	}()
	ctx := ddd.NewContext(context.Background(), "", log.Logger())
	// ctx := ddd.CreateContext(context.Background(), "")
	mgorepo.SetContextDB(ctx, c.d)
	defer mgorepo.ReleaseDB(ctx)

	for m := range c.m {
		if m.infoid != "" {
			c.gs.DeleteAllInfo(ctx, m.infoid)
			continue
		}

		gi := groupd.WrapIa2Gid(ctx, m.g, m.i, c.car)
		m.g.AppendInfo(ctx, gi)
	}
}
func (c *collecting) Del(infoid string) {
	c.m <- &mcoll{
		infoid: infoid,
	}
}
func (c *collecting) AddGroup(g *groupd.GroupAggregate) {
	if len(g.Rules) == 0 {
		return
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	if m, ok := c.gasmap[g.GroupID]; ok {
		if m == g {
			return
		}
	}
	c.gasmap[g.GroupID] = g
	c.gas = make([]*groupd.GroupAggregate, 0, len(c.gasmap))
	for _, tg := range c.gasmap {
		c.gas = append(c.gas, tg)
	}
	log.Infof("信息组(%v)加入收集队列.", g.GroupID)
}
func (c *collecting) DelGroup(g *groupd.GroupAggregate) {
	c.lock.Lock()
	defer c.lock.Unlock()
	if _, ok := c.gasmap[g.GroupID]; ok {
		delete(c.gasmap, g.GroupID)
		c.gas = make([]*groupd.GroupAggregate, len(c.gasmap))
		for _, tg := range c.gasmap {
			c.gas = append(c.gas, tg)
		}

		log.Infof("信息组(%v)离开收集队列.", g.GroupID)
	}
}
func (c *collecting) Append(i *infod.InfoAggregate) {
	c.lock.RLock()
	defer c.lock.RUnlock()
	c.walkGroups(i)
}
func (c *collecting) walkGroups(i *infod.InfoAggregate) {

	ic := groupd.NewInfoColl(i)
	// ic := icoll{
	// 	i:        i,
	// 	owner:    i.Owner,
	// 	org:      i.Org,
	// 	columnid: i.ColumnID,
	// 	content:  i.Title + i.SubTitle + i.Desc + i.Content,
	// 	tags:     make(map[string]bool),
	// }
	// if len(i.Tags) > 0 {
	// 	for _, t := range i.Tags {
	// 		ic.tags[t] = true
	// 	}
	// }
	for _, g := range c.gas {
		if g.MatchGroupInfo(ic) {
			c.m <- &mcoll{
				g: g,
				i: i,
			}
		}
	}

}

type mcoll struct {
	g      *groupd.GroupAggregate
	i      *infod.InfoAggregate
	infoid string
}

// type icoll struct {
// 	i        *infod.InfoAggregate
// 	tags     map[string]bool
// 	owner    string
// 	org      string
// 	columnid string
// 	content  string
// }

// func (c *collecting) matchGroup(g *groupd.GroupAggregate, i icoll) {
// 	defer func() {
// 		if err := recover(); err != nil {
// 			log.Errorf("matchGroup panic:%v", err)
// 			log.Errorf("++++++:%v", string(debug.Stack()))
// 		}
// 	}()
// 	for _, r := range g.Rules {
// 		if r.ColumnID != "" && r.ColumnID != i.columnid {
// 			continue
// 		}
// 		if r.Org != "" && r.Org != i.org {
// 			continue
// 		}
// 		if r.Own != "" && r.Own != i.owner {
// 			continue
// 		}
// 		if r.Tags != nil && len(r.Tags) > 0 {
// 			if len(r.Tags) > len(i.tags) {
// 				continue
// 			}
// 			for _, rt := range r.Tags {
// 				if _, ok := i.tags[rt]; !ok {
// 					continue
// 				}
// 			}
// 		}
// 		if r.Key != "" {
// 			if !strings.Contains(i.content, r.Key) {
// 				continue
// 			}

// 		}
// 		// 匹配成功
// 		c.m <- &mcoll{
// 			g: g,
// 			i: i.i,
// 		}
// 		break
// 	}
// }
